package com.stonedt.spider.serviceImpl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONObject;
import com.stonedt.spider.dao.*;
import com.stonedt.spider.entity.*;
import com.stonedt.spider.service.SmartCollectService;
import com.stonedt.spider.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: 康涵博
 * @ClassName: SmartCollectServiceImpl
 * @Time: 2024/4/25 13:54
 * @Description:
 */
@Service("SmartCollectService")
public class SmartCollectServiceImpl implements SmartCollectService {

    @Autowired
    private SmartCollectDao smartCollectDao;

    @Autowired
    private TripDetailDao tripDetailDao;

    @Autowired
    private ListDetailDao listDetailDao;


    @Autowired
    private SpiderFlowDao spiderFlowDao;

    @Autowired
    private DataSourceDao dataSourceDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private VariableDao variableDao;

    @Override
    @Transactional
    public WebsiteVo addSmartCollect(SmartCollectVo smartCollectVo,HttpServletRequest request) {

        //再向采集任务表中添加数据
        SpiderFlow spiderFlow = new SpiderFlow();
        //任务名称
        spiderFlow.setSeed_name(smartCollectVo.getSmartCollect().getTaskName());
        //优先级（1：高。2：中。3:低）
        spiderFlow.setSpider_level(3);
        //采集方式：1：智能采集。2：低代码采集
        spiderFlow.setCollect_way(1);
        //采集类型：1：网页。2：文件
        spiderFlow.setType(1);
        //运行状态1正常0关闭
        spiderFlow.setSeed_status(0);
        //创建时间是现在
        spiderFlow.setCreate_date(DateTime.now());
        //任务对应网站ID
        spiderFlow.setWebsite_id(smartCollectVo.getSmartCollect().getWebsiteId());

        //任务类型，1代表html 2json 3代表html>cdata(默认是1)
        spiderFlow.setSeed_type(1);
        //数据类型id,默认1
        spiderFlow.setData_type_id(1);
        //唯一标识, 值最好是 该爬虫访问的列表的url
        spiderFlow.setSole_sign(smartCollectVo.getSmartCollect().getTargetUrl());
        //获取用户信息
        String token = request.getHeader("token");
        String user = redisUtil.getKey(token);
        JSONObject jsonObject =  new JSONObject(user);
        Integer userId = jsonObject.getInt("id");
        String username = jsonObject.getStr("username");
        spiderFlow.setCreate_user_id(userId);
        spiderFlow.setCreate_user(username);
        //插入数据
        spiderFlowDao.addSpiderFlow(spiderFlow);

        //返回值填充
        //根据任务对应网站id查询出网站名称
        WebsiteVo websiteVo = new WebsiteVo();
        //种子的id和名称
        websiteVo.setSpiderFlow(spiderFlow);
        DataSource dataSource = dataSourceDao.queryFileNameById(smartCollectVo.getSmartCollect().getWebsiteId());
        //任务列表的id和名称
        websiteVo.setDataSource(dataSource);

        //将智能采集单体数据插入
        SmartCollect smartCollect = new SmartCollect();
        smartCollect.setId(spiderFlow.getId());
        smartCollect.setTargetUrl(smartCollectVo.getSmartCollect().getTargetUrl());
        smartCollect.setAgencyIp(smartCollectVo.getSmartCollect().getAgencyIp());
        smartCollect.setUpdateIp(smartCollectVo.getSmartCollect().getUpdateIp());
        smartCollect.setUrlList(smartCollectVo.getSmartCollect().getUrlList());
        smartCollect.setUnuse(smartCollectVo.getSmartCollect().getUnuse());
        smartCollect.setPageTurnNumber(smartCollectVo.getSmartCollect().getPageTurnNumber());
        smartCollect.setPageTurnWay(smartCollectVo.getSmartCollect().getPageTurnWay());
        smartCollect.setPageTurnButton(smartCollectVo.getSmartCollect().getPageTurnButton());
        smartCollect.setTaskName(smartCollectVo.getSmartCollect().getTaskName());
        smartCollect.setCollectWay(smartCollectVo.getSmartCollect().getCollectWay());
        smartCollect.setWebsiteId(smartCollectVo.getSmartCollect().getWebsiteId());
        smartCollect.setType(0);
        smartCollectDao.addSmartCollect(smartCollect);


        //将智能采集下钻详情遍历插入数据插入到数据库
        TripDetail  tripDetail = new TripDetail();
        smartCollectVo.getTripDetails().forEach(e->{
            tripDetail.setField(e.getField());
            tripDetail.setConfig(e.getConfig());
            tripDetail.setSmartCollectId(spiderFlow.getId());
            //详情表插入数据
            tripDetailDao.addTripDetail(tripDetail);
        });

        //将列表数据配置插入
        ListDetail listDetail = new ListDetail();
        smartCollectVo.getListDetails().forEach(e->{
            listDetail.setField(e.getField());
            listDetail.setConfig(e.getConfig());
            listDetail.setSmartCollectId(spiderFlow.getId());
            //列表配置插入数据
            listDetailDao.addListDetail(listDetail);
        });

        //xml拼接操作
        try {
            XmlVo xmlVo = new XmlVo();
            //获取xml模板
            String xml = xmlVo.getXml();
            //替换utl动态变量
            String newXml = replaceChar(xml, "${weburl}$", smartCollectVo.getSmartCollect().getTargetUrl());
            //替换详情url列表
            newXml = replaceChar(newXml, "${listurl}$", smartCollectVo.getSmartCollect().getUrlList());

            // 1.遍历最全的字典表list，里面包含：title、时间、url、作者等等字典，
            // 2.循环体里嵌套包含：hashmap，如果当前对象中不包含现有字段，则在字典表中新增一条记录
            //3.遍历后判断，前端传过来的键值对中是否包含全量对应字段，如果有缺失，则置空，如果有，则替换对应的值。
            //4.最终输出
            HashMap<String, String> hashMap = new HashMap<>();
            //把前段传过来的集合插入到hashmap中
            for (ListDetail listDetail1 : smartCollectVo.getListDetails()){
                hashMap.put(listDetail1.getField(), listDetail1.getConfig());
            }

            // 遍历HashMap的所有键
            for (String key : hashMap.keySet()) {
                //查询前段传入的变量名是否在字典表存在
                Variable variable = variableDao.queryAlias(key);
                //如果不存在则插入相应的变量
                if(variable == null){
                    variableDao.addVariable(key);
                }
            }

            //查询所有字典表信息
            List<Variable> variableList = new ArrayList<>();
            variableList = variableDao.queryVariableList();
            //遍历后判断，前端传过来的键值对中是否包含全量对应字段，如果有缺失，则置空，如果有，则替换对应的值。
            for (Variable variable : variableList) {
                if (hashMap.containsKey(variable.getAlias())) {
                    variable.setVariableData(hashMap.get(variable.getAlias()));
                } else {
                    variable.setVariableData(null);
                }
                //更新字典表
                variableDao.updateVariable(variable);
            }
            // 同时遍历键和值
            //将xml中变量名插入并拼接
            XmlVo xmlVo1 = new XmlVo();
            String xml1 = xmlVo1.getXml1();
            for (Map.Entry<String, String> entry : hashMap.entrySet()) {
                //拼接变量名
                String targetStr = "&quot;source_url&quot;";
                Variable v  = variableDao.queryVariableName(entry.getKey());
                if(v == null){
                    System.out.println("目录表中未找到变量名请更新");
                }else {
                    String appendStr = ",&quot;"+ v.getVariableName() +"&quot;";
                    int index = xml1.indexOf(targetStr);
                    if (index != -1) {
                        xml1 = xml1.substring(0, index + targetStr.length()) + appendStr + xml1.substring(index + targetStr.length());
                        System.out.println(xml1);
                    } else {
                        System.out.println("未找到变量名对应字符串");
                    }

                    //拼接变量值
                    String targetStr1 = "&quot;${infourl}&quot;";
                    String appendStr1 = ",&quot;${ infohtml.selector(&#39;"+entry.getValue()+"&#39;).text() }&quot;";
                    int index1 = xml1.indexOf(targetStr1);
                    if (index1 != -1) {
                        xml1 = xml1.substring(0, index1 + targetStr1.length()) + appendStr1 + xml1.substring(index1 + targetStr1.length());
                        System.out.println(xml1);
                    } else {
                        System.out.println("未找到变量值对应字符串");
                    }
                }
            }
            //合并两个xml
            String endXml = newXml + xml1;
            //将xml更新插入数据库
            spiderFlowDao.updateXmlById(spiderFlow.getId(),endXml);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return websiteVo;
    }

    /**
     * @Author 康涵博
     * @Description 替换动态变量方法
     * @Date 16:15 2024/5/3
     * @Param [java.lang.String, java.lang.String, java.lang.String]
     * @return java.lang.String
     */
    public static String replaceChar(String xml, String oldStr, String newStr) {
        return xml.replace(oldStr, newStr);
    }


    @Override
    @Transactional
    public SmartCollectVo querySmartCollectById(Integer id) {
        //查询单体内容并返回
        SmartCollect smartCollect = smartCollectDao.querySmartCollectById(id);
        //查询列表内容返回
        List<TripDetail> tripDetails =tripDetailDao.queryTripDetailBySmartCollectId(id);
        //查询字段配置列表并返回
        List<ListDetail>  listDetails = listDetailDao.queryListDetailBySmartCollectId(id);
        SmartCollectVo smartCollectVo = new SmartCollectVo();
        smartCollectVo.setSmartCollect(smartCollect);
        smartCollectVo.setTripDetails(tripDetails);
        smartCollectVo.setListDetails(listDetails);
        return smartCollectVo;
    }

    @Override
    @Transactional
    public void updateSmartCollect(SmartCollectVo smartCollectVo, HttpServletRequest request) {
        //先修改smart_collect表
        smartCollectDao.updateSmartCollect(smartCollectVo.getSmartCollect());
        //在修改下钻详情表
        smartCollectVo.getTripDetails().forEach(e->{
            TripDetail tripDetail = new TripDetail();
            tripDetail.setId(e.getId());
            tripDetail.setField(e.getField());
            tripDetail.setConfig(e.getConfig());
            tripDetail.setSmartCollectId(smartCollectVo.getSmartCollect().getId());
            tripDetailDao.updateTripDetail(tripDetail);
        });
        //修改字段详情配置
        smartCollectVo.getListDetails().forEach(e->{
            ListDetail listDetail = new ListDetail();
            listDetail.setId(e.getId());
            listDetail.setField(e.getField());
            listDetail.setConfig(e.getConfig());
            listDetail.setSmartCollectId(smartCollectVo.getSmartCollect().getId());
            listDetailDao.updateListDetail(listDetail);
        });
        //修改spiderFlow相应字段
        SpiderFlow spiderFlow = new SpiderFlow();
        spiderFlow.setId(smartCollectVo.getSmartCollect().getId());
        spiderFlow.setSeed_name(smartCollectVo.getSmartCollect().getTaskName());
        spiderFlow.setSole_sign(smartCollectVo.getSmartCollect().getTargetUrl());

        //获取用户信息
        String token = request.getHeader("token");
        String user = redisUtil.getKey(token);
        JSONObject jsonObject =  new JSONObject(user);
        Integer userId = jsonObject.getInt("id");
        String username = jsonObject.getStr("username");

        spiderFlow.setUpdate_user_id(userId);
        spiderFlow.setUpdate_user(username);
        spiderFlowDao.updateSpiderFlow(spiderFlow);

    }
}
